/// 
/// MaDAson - Toolkit for Model Driven Software Development
/// 
/// Copyright [2006] Marcus Lankenau
/// 
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///  
///     http://www.apache.org/licenses/LICENSE-2.0
///  
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// 

using System;
using System.Collections.Generic;
using System.IO;

namespace Madason.MetaModel.Solution
{
	/// <summary>
	/// Summary description for Project
	/// </summary>
	public class Project : Namespace
	{
		private Guid visualStudioGuid = Guid.Empty;

		#region properites

		/// <summary>
		/// build target of project for cs compiler (exe, winexe, dll)
		/// </summary>
		public virtual string Target 
		{
			get
			{
				throw new InvalidOperationException("can't get Target of Project");
			}
		}

		/// <summary>
		/// extention for the build target (e.e. exe, dll)
		/// </summary>
		public virtual string Extention
		{
			get
			{
				throw new InvalidOperationException("can't get Extention of Project");
			}
		}


		private List<string> projectFiles = new List<string>();
		public List<string> ProjectFiles
		{
			get
			{
				return projectFiles;
			}
		}


		public string OutputFile
		{
			get
			{
				return FullName + "." + Extention;
			}
		}


		public string ProjectDirectory
		{
			get
			{
				return FullName;
			}
		}

		public virtual List<string> GacReferences
		{
			get
			{
				List<string> list = new List<string>();

				list.Add("System");
				list.Add("System.XML");
				return list;
			}
		}

		public virtual bool NeedNantCompile
		{
			get { return true; }
		}
		#endregion

		/// <summary>
		/// search all contained project files 
		/// </summary>
		/// <param name="basedir"></param>
		/// <param name="dir"></param>
		/// <returns></returns>
		public virtual List<string> FindExistingProjectFiles(DirectoryInfo basedir, DirectoryInfo dir)
		{
			List<string> list = new List<string>();
			int lengthBaseDir = basedir.FullName.Length;

			foreach (FileInfo file in dir.GetFiles("*.cs"))
			{
				list.Add(file.FullName.Substring(lengthBaseDir+1));
			}

			foreach (DirectoryInfo childDir in dir.GetDirectories())
			{
				list.AddRange(FindExistingProjectFiles(basedir, childDir));
			}

			return list;
		}


		
		/// <summary>
		/// generate the directory structure for the project
		/// this contains 
		///		the project directory, 
		///		the visual studio project file
		/// </summary>
		/// <param name="dir"></param>
		public virtual void GenerateDirectoryStructure(DirectoryInfo dir)
		{
			DirectoryInfo maindir = dir.CreateSubdirectory(ProjectDirectory);


			projectFiles = FindExistingProjectFiles(maindir, maindir);

			using (StreamWriter prjWriter = new StreamWriter(maindir.FullName + "\\" + FullName + ".csproj"))
			{
				ProjectFile projectFile = new ProjectFile();
				projectFile.Project = this;
				projectFile.Render(prjWriter);
			}
		}


		public virtual List<string> NantReferences
		{
			get
			{
				List<string> list = new List<string>();

				foreach (string gacref in GacReferences)
					list.Add(gacref + ".dll");

				foreach (Dependency dep in Dependencies)
				{
					if (dep.Target is Project)
					{
						Project depProject = dep.Target as Project;
						list.Add("${build.dir}/"+depProject.OutputFile);
					}
				}

				return list;
			}
		}

		public virtual List<string> NantProjectReferences
		{
			get
			{
				List<string> list = new List<string>();

				foreach (Dependency dep in Dependencies)
				{
					if (dep.Target is Project)
					{
						Project depProject = dep.Target as Project;
						list.Add(depProject.OutputFile);
					}
				}

				return list;
			}
		}

		public ProjectList VisualStudioProjectReferences
		{
			get
			{
				ProjectList list = new ProjectList();
				foreach (Dependency dep in Dependencies)
				{
					if (dep.Target is Project)
					{
						list.Add(dep.Target as Project);
					}
				}
				return list;
			}
		}


		public string VisualStudioGuid
		{
			get
			{
				if (visualStudioGuid == Guid.Empty)
					visualStudioGuid = Guid.NewGuid();
				return visualStudioGuid.ToString("D").ToUpper();
			}
		}

		public virtual string VisualStudioOutputType
		{
			get
			{
				throw new InvalidOperationException("VisualStudioOutputTypee should be overridden");
			}
		}


		public bool DependsOn(Project project)
		{
			foreach (Dependency dep in Dependencies)
			{
				if (dep.Target == project)
					return true;
			}

			foreach (Dependency dep in Dependencies)
			{
				if (dep.Target is Project)
				{
					if ((dep.Target as Project).DependsOn(project))
						return true;
				}
			}
			return false;
		}

	}

	public class ProjectList : List<Project>
	{ }
}